#include <algorithm>
#include <tuple>

#include "common/log/log.h"

#include "session.h"

#include "session_manager.h"

SessionManager::~SessionManager()
{
}

void SessionManager::killExpiredSessions()
{
    std::unique_lock lock(m_locker);
    for (auto it = m_sessions.begin(); it != m_sessions.end();)
    {
        if (!it->second->checkDuration())
            it = m_sessions.erase(it);
        else
            ++it;
    }
}

Elements::UserPtr SessionManager::userBySession(const Uuids::Uuid& uuid)
{
    std::unique_lock lock(m_locker);
    killExpiredSessions();

    auto session = m_sessions.find(uuid);
    if (m_sessions.end() == session)
        return nullptr;

    session->second->keepAlive();
    return session->second->user();
}

Uuids::Uuid SessionManager::createSession(Elements::UserPtr user)
{
    assert(user);
    std::unique_lock lock(m_locker);

    // Если у данного пользователя уже была сессия, её нужно закрыть.
    for (auto it = m_sessions.begin(); it != m_sessions.end();)
    {
        if (user->id() == it->second->user()->id())
            it = m_sessions.erase(it);
        else
            ++it;
    }

    // Новая сессия для пользователя.
    auto session = std::make_shared<Session>(user);
    const auto uuid = session->uuid();
    m_sessions[uuid] = session;
    return uuid;
}

bool SessionManager::removeSession(const Uuids::Uuid& uuid)
{
    std::unique_lock lock(m_locker);
    return (0 != m_sessions.erase(uuid));
}
